import { reactive } from 'vue'
import { service } from '@/configs/axios/service'
import { InterfaceItem, CacheApiName } from './types'
import { Observer } from './helper'
import { cacheApiList } from './cacheApi/index'

// useRequest 观察器
const requestObserver = new Observer()

// interfaceDic build
function buildInterfaceDic(interfaceList: Array<InterfaceItem | CacheApiName>) {
  const interfaceDic: { [key: string]: InterfaceItem | CacheApiName } = {}
  interfaceList.forEach(el => {
    if (typeof el === 'string') {
      interfaceDic[el] = el
    } else if (el.name) {
      interfaceDic[el.name] = el
    }
  })
  return interfaceDic
}

// axios config build
function buildAxiosConfig(interfaceItem: InterfaceItem, params: any, option: any) {
  const reqOpt = {
    ...(interfaceItem.config || {}),
    ...option,
    url: interfaceItem.url,
    method: interfaceItem.method || 'post',
    data: {
      ...(interfaceItem.params || {}),
      ...params
    }
  }

  if (reqOpt.method === 'get') {
    reqOpt.params = reqOpt.data
  }

  return reqOpt
}

// useRequest
export const useRequest = (interfaceList: Array<InterfaceItem | CacheApiName>) => {
  // 接口数据
  const datas = reactive<{ [key: string]: any }>({})

  // 接口字典
  const interfaceDic = buildInterfaceDic(interfaceList)

  // 请求缓存接口
  async function requestCacheApi(interfaceName: string, params: any, option: any) {
    const interfaceItem = cacheApiList.find(el => el.name === interfaceName)
    if (!interfaceItem) {
      throw new Error(`未找到对应接口:${interfaceName}`)
    }

    const res = requestObserver.getCache(interfaceName)
    if (!res) {
      const reqOpt = buildAxiosConfig(interfaceItem, params, option)
      return await service.request(reqOpt).then(res => {
        requestObserver.setCache(interfaceName, res)
        datas[interfaceName] =
          (interfaceItem.responseFormate && interfaceItem.responseFormate(res)) || res

        return datas[interfaceName]
      })
    } else {
      datas[interfaceName] =
        (interfaceItem.responseFormate && interfaceItem.responseFormate(res)) || res
      return datas[interfaceName]
    }
  }

  // 请求接口
  async function requestApi(interfaceName: string, params: any, option: any) {
    const interfaceItem = interfaceDic[interfaceName] as InterfaceItem
    const reqOpt = buildAxiosConfig(interfaceItem, params, option)
    return await service.request(reqOpt).then(res => {
      requestObserver.setCache(interfaceName, res)
      datas[interfaceName] =
        (interfaceItem.responseFormate && interfaceItem.responseFormate(res)) || res

      return datas[interfaceName]
    })
  }

  // 接口请求触发器
  async function exec(interfaceName: string, params?: any, option?: any) {
    if (!interfaceDic[interfaceName]) {
      throw new Error(`未找到对应接口:${interfaceName}`)
    } else if (typeof interfaceDic[interfaceName] === 'string') {
      return await requestCacheApi(interfaceName, params, option)
    } else {
      return await requestApi(interfaceName, params, option)
    }
  }

  // 初始化interface
  interfaceList.forEach(el => {
    if (typeof el === 'string') {
      exec(el)
    } else if (el.isInit) {
      exec(el.name)
    }
  })

  return {
    datas,
    exec
  }
}
